#coding=utf-8
# !/usr/bin/python
# -*- coding: utf-8 -*-

import json
import serial
import serial.tools.list_ports
import time
import sys
import numpy as np

from PyQt5.Qt import *
from matplotlib.backends.backend_qt5 import NavigationToolbar2QT as NavigationToolbar

from user_cfg import * # 用户参数
from dt_ui_res import * # ui资源
from dt_ui_mplot import * # 高速数据曲线图显示
from data_thread import * # 数据处理
from data_devsta import * # 设备状态
from data_highspeed import * # 高速数据



class Window(QMainWindow, Ui_MainWindow):
    def __init__(self, app):
        super(QMainWindow, self).__init__()
        self.setupUi(self) #  QT designer 初始化UI
        self.s1__box_1.clicked.connect(self.port_check)
        self.open_button.clicked.connect(self.port_open)
        self.close_button.clicked.connect(self.port_close)

        self.app = app
        self.cfg = jscfg() # 读取配置数据
        self.user_setup_ui() # 配置UI界面
        self.setup_plot() # 配置plot
        self.ts = time.time()
        self.ser = serial.Serial()
        self.port_check()
        self.devsta = c_devsta()
        self.highspeed = c_highspeed()
        self.dump_en = 0 # 103定时查询
        
        self.update_data_thread = UpdateDataThread(self)  # 创建一个线程
        self.update_data_thread.start()
        self.update_data_thread._signal_update.connect(self.update_data)  # 绑定回调事件

        # 103 定时发送数据
        self.timer1 = QTimer()
        self.timer1.timeout.connect(self.yq103_req)
        self.timer1.start(1000)
        
        #dbg
        self.port_open()

    def yq103_req(self):
        if self.ser.isOpen() and 0 == self.dump_en:
            data = self.devsta.pack_frame_head()
            output_s = self.devsta.pack_frame_tail(data)
            # print(output_s, flush = True)
            num = self.ser.write(output_s)
        else:
            pass

    
    def yq103_buttonpush_send(self):
        if self.ser.isOpen():
            data = self.devsta.pack_frame_head()
            data = self.devsta.c_matain.pack_matain_msg(data)
            output_s = self.devsta.pack_frame_tail(data)
            # print(output_s, flush = True)
            num = self.ser.write(output_s)
        else:
            pass    
        
    def user_setup_ui(self):
        self.edit6.setText("0KB")
        
        # 配置数据选择项
        self.data_sel1.setChecked(bool(self.cfg.data['dsel'][0]))
        self.data_sel2.setChecked(bool(self.cfg.data['dsel'][1]))
        self.data_sel3.setChecked(bool(self.cfg.data['dsel'][2]))
        self.data_sel4.setChecked(bool(self.cfg.data['dsel'][3]))
        self.data_sel5.setChecked(bool(self.cfg.data['dsel'][4]))
        self.data_sel6.setChecked(bool(self.cfg.data['dsel'][5]))

        # 配置数据放大倍数
        self.ddvi1.setCurrentIndex(self.cfg.data['ddiv'][0])
        self.ddvi2.setCurrentIndex(self.cfg.data['ddiv'][1])
        self.ddvi3.setCurrentIndex(self.cfg.data['ddiv'][2])
        self.ddvi4.setCurrentIndex(self.cfg.data['ddiv'][3])
        self.ddvi5.setCurrentIndex(self.cfg.data['ddiv'][4])
        self.ddvi6.setCurrentIndex(self.cfg.data['ddiv'][5])

        self.data_sel1.stateChanged.connect(self.data_selecter)
        self.data_sel2.stateChanged.connect(self.data_selecter)
        self.data_sel3.stateChanged.connect(self.data_selecter)
        self.data_sel4.stateChanged.connect(self.data_selecter)
        self.data_sel5.stateChanged.connect(self.data_selecter)
        self.data_sel6.stateChanged.connect(self.data_selecter)

        self.ddvi1.currentIndexChanged.connect(self.data_dvicb)
        self.ddvi2.currentIndexChanged.connect(self.data_dvicb)
        self.ddvi3.currentIndexChanged.connect(self.data_dvicb)
        self.ddvi4.currentIndexChanged.connect(self.data_dvicb)
        self.ddvi5.currentIndexChanged.connect(self.data_dvicb)
        self.ddvi6.currentIndexChanged.connect(self.data_dvicb)
        
    def user_setup_devsta(self):
        self.ctlsel1.stateChanged.connect(self.data_selecter)

  
    def setup_plot(self):
        self.phase_fig = c_Mplplot(width=5, height=3, dpi=72)
        self.fig_ntb = NavigationToolbar(self.phase_fig, self)
        self.gridlayout = QGridLayout(self.plot_view)
        self.gridlayout.addWidget(self.phase_fig)
        self.gridlayout.addWidget(self.fig_ntb)
        x_data = np.arange(0, 0.1, 0.1)
        y_data = np.repeat(0, 1)
        self.phase_fig.add_line(1000, x_data, y_data)
        plt.tight_layout()
    
    # 串口检测
    def port_check(self):
        # 检测所有存在的串口，将信息存储在字典中
        self.Com_Dict = {}
        port_list = list(serial.tools.list_ports.comports())
        self.s1__box_2.clear()

        for port in port_list:
            self.Com_Dict["%s" % port[0]] = "%s" % port[1]
            self.s1__box_2.addItem(port[0])
            print(self.s1__box_2.currentText())
            

            
    def port_open(self):
        self.ser.port = self.s1__box_2.currentText()
        self.ser.baudrate = int(self.s1__box_3.currentText())
        self.ser.bytesize = 8 # 8数据位
        self.ser.stopbits = 1 # 1停止位
        self.ser.parity = "N" # 无校验
        try:
            self.ser.open()
        except:
            QMessageBox.critical(self, "Port Error", "此串口无法打开")
            return None
        self.ser.set_buffer_size(40960)
        # 打开串口接收定时器，周期为2-10ms
        self.data_num_received = 0
        self.edit6.setText("0B")
        if self.ser.isOpen():
            self.open_button.setEnabled(False)
            self.close_button.setEnabled(True)
            self.formGroupBox1.setTitle("串口打开")
            
    # 数据选择控件回调
    def data_selecter(self, arg):
        if self.data_sel1.isChecked():
            self.cfg.data['dsel'][0] = 1
        else:
            self.cfg.data['dsel'][0] = 0
            
        if self.data_sel2.isChecked():
            self.cfg.data['dsel'][1] = 1
        else:
            self.cfg.data['dsel'][1] = 0
            
        if self.data_sel3.isChecked():
            self.cfg.data['dsel'][2] = 1
        else:
            self.cfg.data['dsel'][2] = 0
            
        if self.data_sel4.isChecked():
            self.cfg.data['dsel'][3] = 1
        else:
            self.cfg.data['dsel'][3] = 0
            
        if self.data_sel5.isChecked():
            self.cfg.data['dsel'][4] = 1
        else:
            self.cfg.data['dsel'][4] = 0 
            
        if self.data_sel6.isChecked():
            self.cfg.data['dsel'][5] = 1
        else:
            self.cfg.data['dsel'][5] = 0   
        # 更新数据    
        self.update_data_thread_slot()

    # 数据放大比例控件回调
    def data_dvicb(self, arg):
        prinf( arg )
        self.cfg.data['ddiv'][0] = (self.ddvi1.currentIndex())
        self.cfg.data['ddiv'][1] = (self.ddvi2.currentIndex())
        self.cfg.data['ddiv'][2] = (self.ddvi3.currentIndex())
        self.cfg.data['ddiv'][3] = (self.ddvi4.currentIndex())
        self.cfg.data['ddiv'][4] = (self.ddvi5.currentIndex())
        self.cfg.data['ddiv'][5] = (self.ddvi6.currentIndex())
        # 更新数据
        self.update_data_thread_slot()

    # 关闭串口
    def port_close(self):
        try:
            self.ser.close()
        except:
            pass
        self.open_button.setEnabled(True)
        self.close_button.setEnabled(False)

        # 接收数据和发送数据数目置零        
        self.formGroupBox1.setTitle("串口关闭")
        self.cfg.save()
    def update_data(self, info):
        if "0" == info:
            self.update_data_thread_slot()
        elif "1" == info:
            self.update_data_thread_sta()
        else:
            print("info wrong")
            
    def update_data_thread_sta(self):
        self.edit1.setText(self.devsta.str_dzyt_mode())
        self.edit2.setText("{:.1f}Pa".format(self.devsta.sample_pe/10))
        self.edit3.setText("{:d}mA".format(self.devsta.dval1_current))
        self.edit4.setText("{:d}mA".format(self.devsta.dval1_current))
        self.edit5.setText("{:d}mA".format(self.devsta.eval_current))
        
    def update_data_thread_slot(self):
 
        if len(self.highspeed.ga_x) == 0: 
            print("len(self.highspeed.ga_x) == 0");
            return
        dotlist = [0.01, 0.1, 1, 10, 100]
        da1 = np.dot(self.highspeed.ga_pe, dotlist[self.cfg.data['ddiv'][0]])
        da2 = np.dot(self.highspeed.ga_pec, dotlist[self.cfg.data['ddiv'][1]])
        da3 = np.dot(self.highspeed.ga_mspeed, dotlist[self.cfg.data['ddiv'][2]])
        da4 = np.dot(self.highspeed.ga_new, dotlist[self.cfg.data['ddiv'][3]])
        da5 = np.dot(self.highspeed.ga_mpos, dotlist[self.cfg.data['ddiv'][4]])
        da6 = np.dot(self.highspeed.ga_rpos, dotlist[self.cfg.data['ddiv'][5]])
        maxy = 0
        miny = 100000
            
        if self.cfg.data['dsel'][0] == 1:
            # 更新lin1数据
            self.phase_fig.line1.set_ydata( da1 )
            self.phase_fig.line1.set_xdata(self.highspeed.ga_x)
            maxy = max(maxy, np.max(da1))
            miny = min(miny, np.min(da1))
        else:
            self.phase_fig.line1.set_ydata( None )
            self.phase_fig.line1.set_ydata( None )
            
        if self.cfg.data['dsel'][1] == 1:    
            self.phase_fig.line2.set_ydata( da2 )
            self.phase_fig.line2.set_xdata(self.highspeed.ga_x)
            maxy = max(maxy, np.max(da2))
            miny = min(miny, np.min(da2))
        else:
            self.phase_fig.line2.set_ydata( None )
            self.phase_fig.line2.set_ydata( None )
    
        if self.cfg.data['dsel'][2] == 1:    
            self.phase_fig.line3.set_ydata( da3 )
            self.phase_fig.line3.set_xdata(self.highspeed.ga_x)
            maxy = max(maxy, np.max(da3))
            miny = min(miny, np.min(da3))
        else:
            self.phase_fig.line3.set_ydata( None )
            self.phase_fig.line3.set_ydata( None )

        if self.cfg.data['dsel'][3] == 1:    
            self.phase_fig.line4.set_ydata( da4 )
            self.phase_fig.line4.set_xdata(self.highspeed.ga_x)
            maxy = max(maxy, np.max(da4))
            miny = min(miny, np.min(da4))
        else:
            self.phase_fig.line4.set_ydata( None )
            self.phase_fig.line4.set_ydata( None )

        if self.cfg.data['dsel'][4] == 1:    
            self.phase_fig.line5.set_ydata( da5 )
            self.phase_fig.line5.set_xdata(self.highspeed.ga_x)
            maxy = max(maxy, np.max(da5))
            miny = min(miny, np.min(da5))
        else:
            self.phase_fig.line5.set_ydata( None )
            self.phase_fig.line5.set_ydata( None )   
            
        if self.cfg.data['dsel'][5] == 1:    
            self.phase_fig.line6.set_ydata( da6 )
            self.phase_fig.line6.set_xdata(self.highspeed.ga_x)
            maxy = max(maxy, np.max(da6))
            miny = min(miny, np.min(da6))
        else:
            self.phase_fig.line6.set_ydata( None )
            self.phase_fig.line6.set_ydata( None ) 

               # 线程回调函数
        # 设置坐标
        #inya = [abs(np.min(da1)), abs(np.min(da2)), abs(np.min(da3)), abs(np.min(da4)), abs(np.min(da5)), abs(np.min(da6))
        #       ,abs(np.max(da1)), abs(np.max(da2)), abs(np.max(da3)), abs(np.max(da4)), abs(np.max(da5)), abs(np.max(da6))]
        # print(minya)
        #axy = max(minya)

        '''
        if maxy > 5000:
            maxy = maxy *2
        elif maxy > 1600:
            maxy = 5000
        elif maxy > 800 :
            maxy = 2000
        elif maxy > 400:
            maxy = 1000
        elif maxy > 200:
            maxy = 500
        elif maxy > 100: 
            maxy = 300
        else:
            maxy = 100
        '''
        
        #maxy = (maxy*1.1)
        #miny = (miny*1.1)
    

        ymax_int = int(maxy)
        ymin_int = int(miny)
        print(maxy, miny, ymax_int, ymin_int)
        ymax_int = (ymax_int+99)*100/100
        ymin_int = (ymin_int-99)*100/100
        
        xlim0 = np.min(self.highspeed.ga_x)
        xlim1 = np.max(self.highspeed.ga_x)
        
        if xlim1 < self.highspeed.dt_xmax/1000:
            xlim1 = self.highspeed.dt_xmax/1000
            
        self.phase_fig.axes.set_xlim(xlim0, xlim1) 
        
        self.phase_fig.axes.set_ylim(ymin_int, ymax_int) 
            
        self.phase_fig.draw()  # 重新画图




def main():
    app = QApplication(sys.argv)
    mywindow = Window(app)
    mywindow.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
